package com.godyao.mall.pms.service.impl;

import cn.hutool.core.util.ArrayUtil;
import com.godyao.mall.pms.entity.CategoryBrandRelationEntity;
import com.godyao.mall.pms.service.CategoryBrandRelationService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.godyao.mall.core.utils.PageUtils;
import com.godyao.mall.core.utils.Query;

import com.godyao.mall.pms.dao.CategoryDao;
import com.godyao.mall.pms.entity.CategoryEntity;
import com.godyao.mall.pms.service.CategoryService;
import org.springframework.transaction.annotation.Transactional;


@Service("categoryService")
@RequiredArgsConstructor
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {
    private final CategoryBrandRelationService categoryBrandRelationService;


    @Override
    public List<CategoryEntity> listTree() {
        final List<CategoryEntity> categoryEntities = baseMapper.selectList(null);
        final List<CategoryEntity> root = categoryEntities.parallelStream().filter(categoryEntity -> categoryEntity.getParentCid().equals(0L)).collect(Collectors.toList());
        final List<CategoryEntity> result = root.parallelStream()
                .peek(categoryEntity -> categoryEntity.setChildren(getChildren(categoryEntity, categoryEntities)))
                .sorted(Comparator.comparing(categoryEntity1 -> Optional.ofNullable(categoryEntity1.getSort()).orElse(0)))
                .collect(Collectors.toList());
        return result;
    }

    private List<CategoryEntity> getChildren(CategoryEntity categoryEntity, List<CategoryEntity> root) {
        return root.parallelStream().filter(categoryEntity1 ->
                        categoryEntity.getCatId().equals(categoryEntity1.getParentCid()))
                .peek(categoryEntity1 -> categoryEntity1.setChildren(getChildren(categoryEntity1, root)))
                .sorted(Comparator.comparing(categoryEntity1 -> Optional.ofNullable(categoryEntity1.getSort()).orElse(0)))
                .collect(Collectors.toList());
    }

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CategoryEntity> page = this.page(
                new Query<CategoryEntity>().getPage(params),
                new QueryWrapper<CategoryEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateCascade(CategoryEntity category) {
        this.updateById(category);
        categoryBrandRelationService.lambdaUpdate()
                .set(CategoryBrandRelationEntity::getCatelogName, category.getName())
                .eq(CategoryBrandRelationEntity::getCatelogId, category.getCatId())
                .update();
    }

    @Override
    public Long[] getPathById(Long attrGroupId) {
        final List<Long> path = new ArrayList<>();
        addParentNode(attrGroupId, path);
        return  ArrayUtil.reverse(ArrayUtil.toArray(path, Long.class));
    }

    private void addParentNode(Long catId, List<Long> path) {
        path.add(catId);
        final CategoryEntity byId = this.getById(catId);
        if (!byId.getParentCid().equals(0L)) {
            addParentNode(byId.getParentCid(), path);
        }
    }
}
